/**
 * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
 */
package com.jeesite.modules.sd.web;

import com.alibaba.fastjson.JSON;
import com.jeesite.common.collect.ListUtils;
import com.jeesite.common.collect.MapUtils;
import com.jeesite.common.config.Global;
import com.jeesite.common.entity.Extend;
import com.jeesite.common.entity.Page;
import com.jeesite.common.lang.DateUtils;
import com.jeesite.common.lang.ObjectUtils;
import com.jeesite.common.mybatis.mapper.query.QueryType;
import com.jeesite.common.web.BaseController;
import com.jeesite.modules.sd.common.constants.GlobalEnum;
import com.jeesite.modules.sd.common.constants.RecvConstant;
import com.jeesite.modules.sd.common.json.OfficeJson;
import com.jeesite.modules.sd.common.util.GenCodeUtils;
import com.jeesite.modules.sd.entity.*;
import com.jeesite.modules.sd.service.DocDeliverRecordService;
import com.jeesite.modules.sd.service.DocRecvService;
import com.jeesite.modules.sd.service.DocRedisService;
import com.jeesite.modules.sd.service.UppUnitService;
import com.jeesite.modules.sys.entity.EmpUser;
import com.jeesite.modules.sys.entity.Employee;
import com.jeesite.modules.sys.entity.Office;
import com.jeesite.modules.sys.service.EmpUserService;
import com.jeesite.modules.sys.service.OfficeService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 来文登记表Controller
 *
 * @author zhanchj
 * @version 2020-06-30
 */
@Controller
@RequestMapping(value = "${adminPath}/sd/docRecv")
public class DocRecvController extends BaseController {

    @Autowired
    private DocRecvService docRecvService;

    @Autowired
    private DocDeliverRecordService recordService;

    @Autowired
    private OfficeService officeService;

    @Autowired
    private EmpUserService empUserService;

    @Autowired
    private UppUnitService uppUnitService;

    @Autowired
    private DocRedisService docRedisService;


    /**
     * 获取数据
     */
    @ModelAttribute
    public DocRecv get(String id, boolean isNewRecord) {
        return docRecvService.get(id, isNewRecord);
    }

    /**
     * 查询列表
     */
    @RequiresPermissions("sd:docRecv:view")
    @RequestMapping(value = {"list", ""})
    public String list(DocRecv docRecv, Model model) {
        model.addAttribute("docRecv", docRecv);
        return "modules/sd/docRecvList";
    }

    /**
     * 查询列表
     */
    @RequiresPermissions("sd:docRecv:view")
    @RequestMapping(value = {"index", ""})
    public String index(DocRecv docRecv, Model model) {
        model.addAttribute("docRecv", docRecv);
        return "modules/sd/docRecvIndex";
    }

    /**
     * 查询列表数据
     */
    @RequiresPermissions("sd:docRecv:view")
    @RequestMapping(value = "listData")
    @ResponseBody
    public Page<DocRecv> listData(DocRecv docRecv, HttpServletRequest request, HttpServletResponse response) {
        docRecv.setPage(new Page<>(request, response));
        Page<DocRecv> page = docRecvService.findPage(docRecv);
        page.getList().forEach(recv->{
            DocDeliverRecord docDeliverRecord = new DocDeliverRecord();
            docDeliverRecord.getSqlMap().getWhere().and("deliver_type", QueryType.IN,new String[]{"2","3"});
            docDeliverRecord.setDocId(recv.getId());
            recv.setCounts(recordService.findCount(docDeliverRecord));
        });

        return page;
    }

    /**
     * 查看编辑表单
     */
    @RequiresPermissions("sd:docRecv:view")
    @RequestMapping(value = "form")
    public String form(DocRecv docRecv, Model model) {

        model.addAttribute("docRecv", docRecv);
        return "modules/sd/docRecvForm";
    }

    /**
     * 保存数据
     */
    @RequiresPermissions("sd:docRecv:edit")
    @PostMapping(value = "save")
    @ResponseBody
    public String save(@Validated DocRecv docRecv, String isProposed) {

        docRecvService.save(docRecv, isProposed);
        return renderResult(Global.TRUE, text("文件保存成功！"));
    }


    /**
     * 删除数据
     */
    @RequiresPermissions("sd:docRecv:edit")
    @RequestMapping(value = "delete")
    @ResponseBody
    public String delete(DocRecv docRecv) {

        // 文件状态为 0待分发（登记时和拟办完） 才可删除
        if (!GlobalEnum.DOC_STATUS_WAIT.getKey().equals(docRecv.getDocStatus())) {
            return renderResult(Global.FALSE, text("当前状态文件不可删除!"));
        }

        // 是否有过拟办或分发记录
        if (recordService.hasRecord(docRecv.getId())) {
            return renderResult(Global.FALSE, text("当前文件已拟办不可删除!"));
        }

        docRecvService.delete(docRecv);
        return renderResult(Global.TRUE, text("文件删除成功！"));
    }


    /**
     * 拟办
     *
     * @param docRecv
     * @return
     */
    @RequiresPermissions("sd:docRecv:edit")
    @RequestMapping(value = "proposed")
    @ResponseBody
    public String proposed(DocRecv docRecv) {
        // 不是待分发的文件不可拟办
        if (!GlobalEnum.DOC_STATUS_WAIT.getKey().equals(docRecv.getDocStatus())) {
            return renderResult(Global.FALSE, text("当前文件状态不可拟办!"));
        }
        Office office = new Office();
        Extend extend = new Extend();
        extend.setExtendS1(GlobalEnum.OFFICE_TYPE_PROPOSED.getKey());
        office.setExtend(extend);
        List<Office> list = officeService.findList(office);
        // 判断是否有拟办单位
        if (CollectionUtils.isEmpty(list)) {
            return renderResult(Global.FALSE, "请先设置拟办单位!");
        }
        try {
            docRecvService.proposed(docRecv, list.get(0));
            return renderResult(Global.TRUE, text("文件拟办成功!"));
        }catch (Exception e){
            logger.error("拟办文件操作失败,错误信息:{},具体错误内容:{}",e.getMessage(),e.getStackTrace());
            return renderResult(Global.FALSE, text("系统错误,请联系开发人员!"));

        }
    }

    /**
     * 跳转到分发页面
     *
     * @return
     */
    @RequiresPermissions("sd:docRecv:edit")
    @RequestMapping("toDistribute")
    public String toDistribute(DocRecv docRecv, Model model) {
        // 规定领取归还时间
        model.addAttribute("beforeTakeDate",DateUtils.addDays(new Date(),Global.getConfigToInteger("doc.take.days","7")));
        model.addAttribute("beforeReturnDate",DateUtils.addDays(new Date(),Global.getConfigToInteger("doc.return.days","14")));
        model.addAttribute("docRecv", docRecv);
        return "modules/sd/distribute";
    }

    /**
     * 跳转到查看页面
     *
     * @return
     */
    @RequiresPermissions("sd:docRecv:edit")
    @RequestMapping("viewDoc")
    public String viewDoc(DocRecv docRecv, Model model) {
        DocLog log = new DocLog();
        log.setDocId(docRecv.getId());
        log.setSecLvl(docRecv.getSecLvl());
        model.addAttribute("docLog",log);
        model.addAttribute("docRecv",docRecv);
        return "modules/sd/docView";
    }

    /**
     * 跳转到查看页面
     *
     * @return
     */
    @RequiresPermissions("sd:docRecv:edit")
    @RequestMapping("viewRecord")
    public String viewRecord(DocRecv docRecv, Model model) {
        DocDeliverRecord docDeliverRecord = new DocDeliverRecord();
        docDeliverRecord.setDocId(docRecv.getId());
        model.addAttribute("docDeliverRecord", docDeliverRecord);
        model.addAttribute("docRecv", docRecv);
        return "modules/sd/docRecord";
    }


    /**
     * 文件分发
     *
     * @param docRecv 分发文件信息
     * @param userDataScopeListJson 单位信息json数组 {"ctrlType":"OfficeSend","ctrlData":"457301"}
     * @param beforeTakeDate        规定领取时间
     * @param beforeReturnDate      规定归还时间
     * @param isPrint      是否打印 1是 0否
     * @return 文件分发结果
     */
    @RequiresPermissions("sd:docRecv:edit")
    @RequestMapping(value = "distribute")
    @ResponseBody
    public String distribute(DocRecv docRecv,
                             String userDataScopeListJson,
                             Date beforeTakeDate,
                             Date beforeReturnDate,
                             String isPrint) {
        DocRecv recv = docRecvService.get(docRecv);
        // 判断当前文件是否为待分发状态或已分发
        if (GlobalEnum.DOC_STATUS_PREPARATION.getKey().equals(recv.getDocStatus())) {
            return renderResult(Global.FALSE, "当前文件正在拟办无法分发!");
        }
        // 将前台传过来的json字符串转换为对象
        List<OfficeJson> officeJsons = JSON.parseArray(userDataScopeListJson, OfficeJson.class);
        if (CollectionUtils.isEmpty(officeJsons)) {
            return renderResult(Global.FALSE, "分发单位不能为空!");
        }

        List<Office> offices = ListUtils.newArrayList();
        List<String> returnInfos = new ArrayList<>();
        // 若有送文单位
        AtomicBoolean hasSecretariatUser = new AtomicBoolean(true);
        // 过滤非叶子节点
        officeJsons.forEach(json -> {
            Office office = officeService.get(json.getCtrlData());
            if (office.getIsTreeLeaf()) {
                // 送文单位不需要判断该单位是否有人
                if (RecvConstant.OFFICE_DELIVER_TYPE_SEND.equals(json.getCtrlType())) {
                    if (Objects.isNull(recordService.getSecretariatUser())) {
                        hasSecretariatUser.set(false);
                        return;
                    }
                    offices.add(office);
                } else {
                    EmpUser empUser = new EmpUser();
                    Employee employee = new Employee();
                    employee.setOffice(office);
                    empUser.setEmployee(employee);
                    empUser.setCodes(new String[]{office.getOfficeCode()});
                    List<EmpUser> list = empUserService.findUserListByOfficeCodes(empUser);
                    // 判断当前单位是否有用户
                    if (CollectionUtils.isNotEmpty(list)) {
                        offices.add(office);
                    } else {
                        returnInfos.add(office.getOfficeName());
                    }
                }
            }
        });

        if (!hasSecretariatUser.get()) {
            return renderResult(Global.FALSE, "请先设置秘书处领文人!");
        }
        // 判断是否有单位未设置领文人
        if (CollectionUtils.isNotEmpty(returnInfos)) {
            StringBuilder returnInfo = new StringBuilder();
            for (int i = 0; i < returnInfos.size(); i++) {
                returnInfo.append(returnInfos.get(i)).append(",");
                if (i == 2) {
                    returnInfo.append("等").append(returnInfos.size()).append("个单位");
                    break;
                }
            }
            return renderResult(Global.FALSE, returnInfo.append("未设置领文人"));
        }
        List<DocDeliverRecord> list;
        StringBuilder msg = new StringBuilder("文件分发成功");
        //分发文件 step:1 (首先保障文件正常存储到数据库再执行发送短信和打印二维码的操作)
        try {
            list = docRecvService.distribute(recv, offices, beforeTakeDate, beforeReturnDate);
        } catch (Exception e) {
            logger.error("文件分发出现错误,错误信息:", e);
            return renderResult(Global.FALSE, e.getMessage());
        }
        // 存储短信信息 step:2
        try {
            docRedisService.sendInsertRedis(list);
        } catch (Exception e) {
            logger.error("存储短信信息出错,错误信息:", e);
            msg.append(",短信发送失败:").append(e.getMessage());
        }

        return renderResult(Global.TRUE, msg.toString(),list);

    }


    /**
     * 分发后打印二维码.
     *
     * @param list 分发记录list
     * @return the string
     * @author 湛承俊
     * @date 2020 -08-07 15:23:33
     */
    @RequiresPermissions("sd:docRecv:edit")
    @RequestMapping(value = "/printCodeByList")
    @ResponseBody
    public String printCodeByList(@RequestBody List<DocDeliverRecord> list) {
        try {
            docRecvService.printCode(list);
            return renderResult(Global.TRUE, "二维码打印成功!");
        } catch (Exception e) {
            return renderResult(Global.FALSE, "二维码打印失败:{}", e.getMessage());
        }
    }


    /**
     * 打印二维码
     */
    @RequiresPermissions("sd:docRecv:edit")
    @RequestMapping(value = "printCode")
    @ResponseBody
    public String printCode(DocRecv docRecv) {
        // 打印二维码
        try {
            DocDeliverRecord record = new DocDeliverRecord();
            record.setDocId(docRecv.getId());
            String[] in = {GlobalEnum.RECORD_DELIVER_TYPE_DELIVER.getKey(),GlobalEnum.RECORD_DELIVER_TYPE_SEND.getKey()};
            record.getSqlMap().getWhere().and("deliver_type", QueryType.IN,in);
            List<DocDeliverRecord> records = recordService.findList(record);
            if(CollectionUtils.isEmpty(records)){
                return renderResult(Global.FALSE,"当前文件无分发记录!");
            }
            docRecvService.printCode(records);
            return renderResult(Global.TRUE, text("二维码打印中!"));
        }catch (Exception e){
            return renderResult(Global.FALSE,e.getMessage());
        }

    }


    /**
     *  发送短信.
     *
     * @param docRecv {@link DocRecv}
     * @return the string
     * @author 湛承俊
     * @date 2020 -08-06 10:11:47
     */
    @RequiresPermissions("sd:docRecv:edit")
    @RequestMapping(value = "sendMsg")
    @ResponseBody
    public String sendMsg(DocRecv docRecv) {
        DocDeliverRecord query = new DocDeliverRecord();
        // 查询类型为分发给下级和送文的recordList
        query.getSqlMap().getWhere().and("deliver_type",QueryType.IN,new String[]{GlobalEnum.RECORD_DELIVER_TYPE_DELIVER.getKey(),GlobalEnum.RECORD_DELIVER_TYPE_SEND.getKey()});
        query.setDocId(docRecv.getId());
        List<DocDeliverRecord> records = recordService.findList(query);
        // 发送短信
        try {
            docRedisService.sendInsertRedis(records);
            return renderResult(Global.TRUE, text("短信发送成功!"));
        }catch (Exception e){
            logger.error("发送短信失败,错误信息:",e);
            return renderResult(Global.FALSE,e.getMessage());
        }

    }

    /**
     * 获取送文领文单位
     *
     * @param isSendOffice 是否查询送文单位
     * @return
     */
    @RequiresPermissions({"sd:docRecv:edit"})
    @RequestMapping({"treeData"})
    @ResponseBody
    public List<Map<String, Object>> treeData(@RequestParam(value = "isSendOffice", defaultValue = "false") Boolean isSendOffice,
                                              @RequestParam("docId")String docId) {
        List<Map<String, Object>> mapList = ListUtils.newArrayList();
        Office where = new Office();
        where.setStatus("0");
        Extend extend = new Extend();
        //查询已分发的文件列表(未归还)
        DocDeliverRecord record = new DocDeliverRecord();
        record.setDocId(docId);
        record.getSqlMap().getWhere().and("deliver_type",QueryType.IN,new String[]{"2","3"});
        record.getSqlMap().getWhere().and("return_date",QueryType.IS_NULL,null);
        List<DocDeliverRecord> takeList = recordService.findList(record);
        //查询已归还列表(已归还)
        DocDeliverRecord returns = new DocDeliverRecord();
        returns.setDocId(docId);
        returns.getSqlMap().getWhere().and("return_date",QueryType.IS_NOT_NULL,null);
        List<DocDeliverRecord> returnList = recordService.findList(returns);

        // 送文单位
        if (isSendOffice) {
            extend.setExtendS1(GlobalEnum.OFFICE_TYPE_SEND.getKey());
            // 领文单位
        } else {
            extend.setExtendS1(GlobalEnum.OFFICE_TYPE_GET.getKey());
        }
        where.setExtend(extend);
        List<Office> list = this.officeService.findList(where);

        list.forEach(office -> {
            if (RecvConstant.STATUS_NORMAL.equals(office.getStatus())) {
                Map<String, Object> map = MapUtils.newHashMap();
                map.put("id", office.getId());
                map.put("pId", office.getParentCode());
                StringBuilder name = new StringBuilder(office.getOfficeName());

                long count = takeList.stream().filter(takeRecord -> takeRecord.getRecvUnitCode().equals(office.getOfficeCode())).count();
                long countReturn = returnList.stream().filter(takeRecord -> takeRecord.getRecvUnitCode().equals(office.getOfficeCode())).count();
                if(count>0){
                    name.append("(").append("已发").append(")");
                }else if(countReturn>0){
                    name.append("(").append("已还").append(")");
                }

                map.put("name", name);
                map.put("title", office.getFullName());
                mapList.add(map);
            }
        });

        return mapList;
    }


    /**
     * 生成来文自编码
     *
     * @param unitId
     * @return
     */
    @ResponseBody
    @RequestMapping("getGenSysCode")
    public String getGenSysCode(String unitId) {
        UppUnit unit = uppUnitService.get(unitId);
        Long count = docRecvService.findCountByUnitIdAndYear(unitId);
        // 判断是否为当年第一个生成的自编码
        if (count > 0) {
            // 查询最大sysCode截取后四位
            String sysCode = docRecvService.findMaxSysCodeByUnitId(unitId);
            count = Long.parseLong(sysCode.substring(sysCode.length() - 4));
        }
        return GenCodeUtils.getGenDocSysCode(unit.getUnitName(), count);
    }

    /**
     * 跳转到生成短信二维码的页面
     * @param
     * @return
     */
    @RequestMapping("sendMessageView")
    public String sendMessageView() {

        return "modules/sd/docSendMessage";}

    /**
     * 获取数据库中短信的信息
     * @return
     */
    @RequestMapping("getMessageCode")
    @ResponseBody
    public String getMessageCode() {
        MsgManager msgManager;
      //doc.msg.sendLastTime
        Integer configToInteger = Global.getConfigToInteger("doc.msg.checkTime", "0");
        if(configToInteger==1){
            Integer sendFirstTime = Global.getConfigToInteger(" doc.msg.sendFirstTime", "8");
            Integer sendLastTime = Global.getConfigToInteger("doc.msg.sendLastTime", "0");
            Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));
            int hour = cal.get(Calendar.HOUR);
            //只在8点到晚上0点之间发短信
            if(sendLastTime==0){
                sendLastTime=24;
            }
            if (hour <=sendFirstTime) {
                return renderResult(Global.FALSE, text(""));
            }else if ( hour>=sendLastTime){
                return renderResult(Global.FALSE, text(""));
            }

        }

        try {
            msgManager = docRedisService.findAndDeleteRedis();
        } catch (Exception e) {
            return renderResult(Global.FALSE, text("查询失败"));
        }
      if(ObjectUtils.isEmpty(msgManager)){
          return renderResult(Global.FALSE, text(""));
      }
        return renderResult(Global.TRUE, text(""), msgManager);

    }



}